home *** CD-ROM | disk | FTP | other *** search
/ Amiga News 95 / Amiga News 95.iso / dpat / dpat50 / cprg / compc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-23  |  15.0 KB  |  462 lines

  1. /*************************************************************************/
  2. /*                                                                       */
  3. /*               COMPC.C Compression de fichiers source C.               */
  4. /*              V1.00 FREEWARE Christian BRUNON 20-08-1993               */
  5. /*                                                                       */
  6. /*             +-----------------------------------------+               */
  7. /*             | Logiciel placé dans le domaine FREEWARE |               */
  8. /*             +-----------------------------------------+               */
  9. /* L'utilisation et la diffusion de ce programme, des fichiers sources   */
  10. /* et de la documentation sont entièrement libres.                       */
  11. /*                                                                       */
  12. /*                           Christian BRUNON                            */
  13. /*                        30 Rue Georges Brassens                        */
  14. /*                      43140 LA SEAUVE SUR SEMENE                       */
  15. /*                                FRANCE                                 */
  16. /*                                                                       */
  17. /*            Fichier source Lattice C AmigaDOS Version 5.04             */
  18. /*                                                                       */
  19. /*************************************************************************/
  20.  
  21. /* Fichier INCLUDE */
  22. #include "CPRG:CompC.H"
  23.  
  24. /* MACROS */
  25. #define IsValide(C) (((C)=='_') || ((UpChar(C)>'/') && (UpChar(C)<'[')))
  26. #define IsInitiale(C) (((C)=='#') || (IsValide(C)))
  27.  
  28. /* Autre constante d'erreur */
  29. #define CompError 8
  30.  
  31. /* Autre constante */
  32. #define MaxLongLigne 255
  33.  
  34. UBYTE Ligne[MaxLongLigne],     /* Ligne de texte à compresser */
  35.       LigneComp[MaxLongLigne], /* Ligne de texte compressée   */
  36.       NuCar;                   /* Numéro du caractère inséré dans la chaîne Ligne */
  37.  
  38. typedef struct {
  39.                 UWORD CodeMot;
  40.                 UBYTE Mot[MaxLongMot];
  41.                } StructMot;
  42.  
  43. static StructMot ListeMots[MaxMots];
  44.  
  45. static UWORD PosMot;  /* Position du nouveau mot à insérer */
  46.  
  47. static ULONG LongFicOut;
  48.  
  49. const UBYTE *ListeErreurs[] =
  50.      {
  51.       "\n",
  52.       "Utilisation : CompC [-DEST] Fichier1 [-DEST] [Fichier2] [...]\n",
  53.       "\aFichier inexistant\n",
  54.       "\aErreur en création\n",
  55.       "\aErreur en écriture\n",
  56.       "\aErreur en lecture\n",
  57.       "\aPas assez de mémoire\n",
  58.       "\a***BREAK\n",
  59.       "\aCompression inefficace\n"
  60.      };
  61.  
  62. extern int (*_ONBREAK)();
  63.  
  64. /**************************************************************************/
  65.  
  66. int CXBRK()
  67. {
  68.  CodeErreur=BreakError;
  69.  
  70.  return(0);
  71. }
  72.  
  73. /**************************************************************************/
  74.  
  75. #ifdef OOOOOOOOO
  76. /* INUTILISE car provoquant des compressions moins importantes */
  77. int IsValide(UBYTE C)
  78. {
  79.  return((C=='_') | (C=='ç') | (C=='é') | (C=='è') | (C=='ê') |
  80.         (C=='à') | (C=='ù') | (C=='ä') | (C=='ë') | (C=='ï') |
  81.         (C=='ö') | (C=='ü') | (C=='â') | (C=='î') | (C=='ô') |
  82.         (C=='û') | (C=='\'') | ((UpChar(C)>'/') && (UpChar(C)<'[')));
  83. }
  84. #endif
  85.  
  86. /**************************************************************************/
  87.  
  88. UBYTE InsererMot()
  89. {
  90.  register UWORD i;
  91.  
  92.  if(NbMots==0)
  93.    {
  94.     strcpy(ListeMots[0].Mot,Mot);
  95.     ListeMots[0].CodeMot=0;
  96.     NbMots=1;
  97.    }
  98.  else if(NbMots<MaxMots)
  99.    {
  100.     /* Décaler la partie supérieure du tableau pour libérer une place */
  101.     if(PosMot<NbMots) for(i=NbMots;i>PosMot;i--) ListeMots[i]=ListeMots[i-1];
  102.  
  103.     /* Insertion du mot */
  104.     strcpy(ListeMots[PosMot].Mot,Mot);
  105.     ListeMots[PosMot].CodeMot=NbMots;
  106.     NbMots++;
  107.    }
  108.  /* Le dictionnaire est plein */
  109.  else return(CodeErreur=MemoryError);
  110.  
  111.  return(0);
  112. }
  113.  
  114. /**************************************************************************/
  115. /* Recherche un mot dans la liste de ceux déjà enregistrés.               */
  116. /* Si le mot ne s'y trouve pas il est inséré dans la liste par appel à la */
  117. /* fonction InsererMot().                                                 */
  118. /* Elle insère le nouveau mot à la position PosMot si la liste n'est pas  */
  119. /* vide.                                                                  */
  120. /* Si elle est vide, le mot est inséré à la première place                */
  121. /* Cette fonction renvoie 1 si le mot est dans la liste.                  */
  122. /* Sinon, elle l'insère et renvoie 0.                                     */
  123. /**************************************************************************/
  124.  
  125. UBYTE TrouverMot()
  126. {
  127.  /* Le mot est peut-être dans la liste */
  128.  if(NbMots)
  129.      {
  130.       /* Le mot est-il inférieur au dernier mot de la liste ? */
  131.       if(strcmp(ListeMots[NbMots-1].Mot,Mot)>=0)
  132.           {
  133.            PosMot=0;
  134.  
  135.            /* Recherche sur le premier caractère de la chaîne */
  136.            while(ListeMots[PosMot].Mot[0]<Mot[0]) PosMot++;
  137.            /* Recherche sur les autres caractères */
  138.            while(strcmp(ListeMots[PosMot].Mot,Mot)<0) PosMot++;
  139.  
  140.            if(strcmp(ListeMots[PosMot].Mot,Mot)==0)
  141.                 {
  142.                  /* Le mot est déjà dans la liste */
  143.                  CodeMot=ListeMots[PosMot].CodeMot;
  144.                  return(1);
  145.                 }
  146.            else CodeErreur=InsererMot(); /* Le mot n'est pas dans la liste */
  147.           }
  148.       else{
  149.            /* Le mot est plus grand que le dernier mot de la liste */
  150.            /* On l'insère en dernière position.                    */
  151.            PosMot=NbMots;
  152.            CodeErreur=InsererMot();
  153.           } /* if(strcmp(ListeMots[NbMots-1].Mot,Mot)>=0) */
  154.  
  155.      }
  156.  else CodeErreur=InsererMot(); /* Mot non trouvé (NbMots=0) */
  157.  
  158.  return(0);
  159. }
  160.  
  161. /**************************************************************************/
  162.  
  163. UBYTE CompresserLigne()
  164. {
  165.  Ligne[NuCar]='\0';
  166.  
  167.  /* Effacement des espaces se trouvant en fin de chaîne */
  168.  while(NuCar && (Ligne[NuCar-1]==' ' || Ligne[NuCar-1]=='\t')) Ligne[--NuCar]='\0';
  169.  
  170.  if(NuCar==0){
  171.               if(fputc(LigneVide,FOut)==EOF) return(WriteError);
  172.              }
  173.  else{
  174.       NuCar=0;
  175.  
  176.       /* Calcul du nombre d'espaces en début de ligne dans NuCar */
  177.       while(Ligne[NuCar]==' ' || Ligne[NuCar]=='\t') NuCar++;
  178.  
  179.       /* Suppression du nombre d'espaces en début de ligne */
  180.       if(NuCar) strcpy(Ligne,Ligne+NuCar);
  181.  
  182.       /* Ecriture du nombre d'espaces en début de ligne */
  183.       if(fputc(NuCar,FOut)==EOF) return(WriteError);
  184.  
  185.       for(NuCar=0 ; NuCar<strlen(Ligne) && CodeErreur==0;)
  186.          {
  187.           /* Un mot détecté */
  188.           if(IsInitiale(Ligne[NuCar]))
  189.             {
  190.              /* Copie de l'initiale du mot dans le premier car de mot */
  191.              Mot[0]=Ligne[NuCar++];
  192.              LongMot=1;
  193.  
  194.              /* Copie du reste du mot */
  195.              while(IsValide(Ligne[NuCar])) Mot[LongMot++]=Ligne[NuCar++];
  196.              /* Ajout de la parenthèse ouverte ou du crochet ouvert si il suit */
  197.              if(Ligne[NuCar]=='(' || Ligne[NuCar]=='[') Mot[LongMot++]=Ligne[NuCar++];
  198.  
  199.              Mot[LongMot]=0;
  200.  
  201.              /* Ecriture du mot ou de son code */
  202.              if(LongMot<3)
  203.                  {
  204.                   if(fputs(Mot,FOut)) return(WriteError);
  205.                  }
  206.              else{
  207.                   /* Mot répertorié ? */
  208.                   if(TrouverMot())
  209.                       {
  210.                        /* Le mot existe, on écrit son code */
  211.                        if(fprintf(FOut,"%c%c%c",MotExistant,CodeMot&255,CodeMot>>8)==-1) return(WriteError);
  212.                       }
  213.                   /* Nouveau mot */
  214.                   else{
  215.                        /* Le mot est nouveau, on l'écrit encadré par */
  216.                        /* les marques de nouveau mot                 */
  217.                        if(fprintf(FOut,"%c%s%c",NouveauMot,Mot,NouveauMot)==-1) return(WriteError);
  218.                       }
  219.                  } /* if(LongMot<3) */
  220.  
  221.             } /* if(IsInitiale(Ligne[NuCar])) */
  222.  
  223.         /* Début de commentaire */
  224.         else if(Ligne[NuCar]=='/' && Ligne[NuCar+1]=='*')
  225.                {
  226.                 /* Début de commentaire + espace */
  227.                 if(Ligne[NuCar+2]==' ')
  228.                     {
  229.                      NuCar+=3;
  230.                      if(fputc(Commentaire2On,FOut)==EOF) return(WriteError);
  231.                     }
  232.                 else{
  233.                      NuCar+=2;
  234.                      if(fputc(Commentaire1On,FOut)==EOF) return(WriteError);
  235.                     }
  236.                }
  237.  
  238.         /* Fin de commentaire */
  239.         else if(Ligne[NuCar]=='*' && Ligne[NuCar+1]=='/')
  240.                {
  241.                 NuCar+=2;
  242.                 if(fputc(Commentaire1Off,FOut)==EOF) return(WriteError);
  243.                }
  244.  
  245.         /* Espace + fin de commentaire */
  246.         else if(Ligne[NuCar]==' ' && Ligne[NuCar+1]=='*' && Ligne[NuCar+2]=='/')
  247.                {
  248.                 NuCar+=3;
  249.                 if(fputc(Commentaire2Off,FOut)==EOF) return(WriteError);
  250.                }
  251.  
  252.         /* Autre caractère */
  253.         else while(!IsInitiale(Ligne[NuCar]) && Ligne[NuCar])
  254.              if(fputc(Ligne[NuCar++],FOut)==EOF) return(WriteError);
  255.  
  256.          } /* for(NuCar=0;NuCar<strlen(Ligne);) */
  257.  
  258.       if(fputc('\n',FOut)==EOF) return(WriteError);
  259.  
  260.       /* Affichage du nombre d'octets lus */
  261.       if(!ComptLignes++) printf("%7u\b\b\b\b\b\b\b",ftell(FIn));
  262.  
  263.       ComptLignes%=10;
  264.       NuCar=0;
  265.      }
  266.  
  267.  return(CodeErreur);
  268. }
  269.  
  270. /**************************************************************************/
  271.  
  272. UBYTE CompresserFichier()
  273. {
  274.  /* VARIABLE LOCALE */
  275.  register int Car; /* Caractère lu dans le fichier */
  276.  
  277.  /* Le fichier est-il vide ?                                     */
  278.  /* if(((Car=fgetc(FIn))==EOF)&&(feof(FIn)))                     */
  279.  /*        {                                                     */
  280.  /*         printf("Fichier vide.\n");                           */
  281.  /*         return(1);                                           */
  282.  /*        }                                                     */
  283.  /*                                                              */
  284.  /* Fichier non vide : on replace le caractère lu dans le buffer */
  285.  /* ungetc(Car,FIn);                                             */
  286.  
  287.  printf("Création du fichier %s -> %7u -> ",NomFicOut,LongFicIn);
  288.  
  289.  LongFicOut=0L;
  290.  if((FOut=fopen(NomFicOut,"wb"))==NULL) return(CreateError);
  291.  
  292.  Car=fgetc(FIn);
  293.  
  294.  ComptLignes=NuCar=NbMots=0;
  295.  
  296.  while(FIn->_flag==_IOREAD && CodeErreur==0)
  297.       {
  298.        if(Car=='\n') CodeErreur=CompresserLigne();
  299.        else Ligne[NuCar++]=Car;
  300.  
  301.        Car=fgetc(FIn);
  302.       }
  303.  
  304.  /* Erreur en lecture ou fin normal de fichier ? */
  305.  if(FIn->_flag != (_IOREAD|_IOEOF)) return(ReadError);
  306.  
  307.  if(CodeErreur==0 && NuCar) CodeErreur=CompresserLigne();
  308.  
  309.  return(CodeErreur);
  310. }
  311.  
  312. /**************************************************************************/
  313.  
  314. int main(int argc,char *argv[])
  315. {
  316.  /* Déclarations et fonctions de Exec.Library */
  317.  extern struct ExecBase *SysBase;
  318.  extern void FreeMem(void *,long);
  319.  extern void *AllocMem(long,long);
  320.  #pragma syscall AllocMem c6 1002
  321.  #pragma syscall FreeMem d2 902
  322.  
  323.  register struct FileInfoBlock *PtrFIB;
  324.  
  325.  /* Déclarations de variables externes de la DOS.Library */
  326.  extern struct DosLibrary *DOSBase;
  327.  extern BPTR CreateDir(char *);
  328.  extern long DeleteFile(char *);
  329.  extern long SetProtection(char *, ULONG);
  330.  extern LONG SetComment(char *, char *);
  331.  extern LONG Examine(BPTR, struct FileInfoBlock *);
  332.  extern BPTR Lock(char *, LONG);
  333.  extern void UnLock(BPTR);
  334.  #pragma libcall DOSBase CreateDir 78 101
  335.  #pragma libcall DOSBase DeleteFile 48 101
  336.  #pragma libcall DOSBase SetProtection ba 2102
  337.  #pragma libcall DOSBase SetComment b4 2102
  338.  #pragma libcall DOSBase Examine 66 2102
  339.  #pragma libcall DOSBase Lock 54 2102
  340.  #pragma libcall DOSBase UnLock 5a 101
  341.  
  342.  /* VARIABLES LOCALES */
  343.  register UBYTE NuArg,
  344.                 FlagNewDir=0,  /* Changer le répertoire de destination ? */
  345.                 CreerChemin=0, /* Créer le nouveau répertoire ?          */
  346.                 NewChemin[80],
  347.                 FileName[108],
  348.                 Commentaire[80];
  349.  
  350.  register BPTR Clef; /* Paramètre utilisé pour Examine() et CreateDir() */
  351.  
  352.  register ULONG Protection;
  353.  
  354.  /*********************** DEBUT DU CODE DE main() **************************/
  355.  
  356.  _ONBREAK=CXBRK;
  357.  
  358.  printf("CompC V1.00 FREEWARE Christian BRUNON 20-08-1993\n");
  359.  
  360.  /* Pas de paramètre ou paramètre ? */
  361.  if(argc==1 || (argc==2 && argv[1][0]=='?' && argv[1][1]=='\0'))
  362.    {
  363.     printf("%s",ListeErreurs[1]);
  364.     return(1);
  365.    }
  366.  
  367.  if((PtrFIB=(struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),0L))==NULL)
  368.    {
  369.     printf("%s",ListeErreurs[MemoryError]);
  370.     return(MemoryError);
  371.    }
  372.  
  373.  for(NuArg=1;NuArg<argc;NuArg++)
  374.  if(argv[NuArg][0]=='-')
  375.      /* Le paramètre lu est un nouveau chemin */
  376.      {
  377.       FlagNewDir=(UBYTE)1;
  378.       strcpy(NewChemin,&argv[NuArg][1]);
  379.  
  380.       if(NewChemin[0]) CreerChemin=LastChar(NewChemin)!=':' && LastChar(NewChemin)!='/';
  381.  
  382.       if(CreerChemin && NewChemin[0])
  383.         {
  384.          if(Clef=CreateDir(NewChemin)) UnLock(Clef);
  385.  
  386.          strcat(NewChemin,"/");
  387.         }
  388.      }
  389.  /* Le paramètre lu est un fichier à compresser */
  390.  else{
  391.       CodeErreur=0;
  392.       strcpy(NomFicIn,argv[NuArg]);
  393.  
  394.       if(Clef=Lock(NomFicIn,ACCESS_READ))
  395.           {
  396.            /* Test existence et test type = fichier */
  397.            if(Examine(Clef,PtrFIB) && PtrFIB->fib_DirEntryType<0)
  398.                {
  399.                 strcpy(FileName,PtrFIB->fib_FileName);
  400.                 LongFicIn=PtrFIB->fib_Size;
  401.                 Protection=(ULONG)PtrFIB->fib_Protection;
  402.                 strcpy(Commentaire,PtrFIB->fib_Comment);
  403.                }
  404.            else CodeErreur=FileOpenReadError;
  405.  
  406.            UnLock(Clef);
  407.           }
  408.       else CodeErreur=FileOpenReadError;
  409.  
  410.       if(CodeErreur){
  411.                      printf("%s %s",NomFicIn,ListeErreurs[CodeErreur]);
  412.                      continue;
  413.                     }
  414.  
  415.       /* Détermination du nom du fichier compressé */
  416.       if(FlagNewDir)
  417.           {
  418.            strcpy(NomFicOut,NewChemin);
  419.            strcat(NomFicOut,FileName);
  420.           }
  421.       else strcpy(NomFicOut,NomFicIn);
  422.  
  423.       /* Rajout de l'extension ".K" */
  424.       strcat(NomFicOut,".K");
  425.  
  426.       printf("Ouverture du fichier %s\r",NomFicIn);
  427.  
  428.       if(FIn=fopen(NomFicIn,"rb"))
  429.         {
  430.          CodeErreur=CompresserFichier();
  431.  
  432.          /* Affichage du taux de compression ou du texte de l'erreur */
  433.          if(CodeErreur==0)
  434.              {
  435.               printf("%7u => ",LongFicOut=ftell(FOut));
  436.  
  437.               if(LongFicIn && LongFicOut<=LongFicIn)
  438.                 printf("%u %%\n",(((100*(LongFicIn-LongFicOut))/LongFicIn)*10+5)/10);
  439.               else CodeErreur=CompError;
  440.              }
  441.          else printf("\n%s",ListeErreurs[CodeErreur]);
  442.  
  443.          if(FIn)  fclose(FIn);
  444.          if(FOut) fclose(FOut);
  445.  
  446.          if(CodeErreur) DeleteFile(NomFicOut);
  447.          else /* Recopie des bits d'attributs de fichier et du commentaire */
  448.              {
  449.               SetProtection(NomFicOut,Protection);
  450.               SetComment(NomFicOut,Commentaire);
  451.              }
  452.         }
  453.       /* Fichier inexistant ou illisible */
  454.       else printf("\n%s",ListeErreurs[CodeErreur=FileOpenReadError]);
  455.      }
  456.  
  457.  if(PtrFIB) FreeMem(PtrFIB,sizeof(struct FileInfoBlock));
  458.  
  459.  /* Renvoie le code d'erreur du dernier fichier compressé */
  460.  return(CodeErreur);
  461. }
  462.